package com.hyts.agent.filter;

import com.hyts.agent.base.logger.AgentLogger;
import com.hyts.agent.base.param.AgentTransferParam;
import com.hyts.agent.bean.AgentExecuteParam;
import com.hyts.agent.logger.AgentLogManager;
import com.hyts.agent.spi.method.AgentExecuteMethod;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
import net.bytebuddy.implementation.bind.annotation.*;

import java.lang.reflect.Method;
import java.text.MessageFormat;
import java.util.concurrent.Callable;

/**
 * project-name:coffice-toolbox
 * package-name:com.hyts.agent.filter
 * author:Libo/Alex
 * create-date:2019-06-30 02:23
 * copyright:libo-hyts-github
 * email:libo2dev@aliyun.com
 * description:此类主要用于 : 方法执行操作拦截器
 */
@Accessors(chain = true)
public class MethodExecuteInterceptor implements AgentExecuteMethod<AgentExecuteParam> {

    /**
     * 日志输出器
     */
    AgentLogger agentLogger = AgentLogManager.getAgentLogger(MethodExecuteInterceptor.class);

    /**
     * 拦截器操作
     */
    @Getter
    @Setter
    MethodInterceptor methodInterceptor;

    /**
     * 之前操作
     * @param targetSubject
     * @param params
     * @param method
     * @return
     */
    @Override
    public Object before(Object targetSubject, Object[] params, Method method, AgentExecuteParam executeParam) {
        agentLogger.debug(MessageFormat.format("执行前置拦截器操作服务 - 开始:{0} - {1}",
                targetSubject.getClass().getName(),method.getName()));
        try {
            methodInterceptor.before(targetSubject,params,method,executeParam.getAgentTransferParam());
        } catch (Exception e) {
            executeParam.setExecuteProtoMethod(false);
            executeParam.setExecuteAfterMethod(false);
            agentLogger.error("前置方法执行失败:"+e);
        }
        agentLogger.debug(MessageFormat.format("执行前置拦截器操作服务 - 结束:{0}",method.getName()));
        return params;
    }

    /**
     * 之后操作
     * @param targetSubject
     * @param params
     * @param method
     * @param result
     * @return
     */
    @Override
    public Object after(Object targetSubject, Object[] params, Method method, Object result, AgentExecuteParam executeParam) {
        agentLogger.debug(MessageFormat.format("执行后置拦截器操作服务 - 开始 结果:{0}",result));
        Object after = null;
        try {
            after = methodInterceptor.after(targetSubject,params,method,result,executeParam.getAgentTransferParam());
        } catch (Exception e) {
            agentLogger.error("后置方法执行失败:"+e);
        }
        agentLogger.debug(MessageFormat.format("执行后置拦截器操作服务 - 结束:{0}",after));
        return after;
    }

    /**
     * 执行异常操作服务
     * @param throwable
     * @param executeParam
     */
    @Override
    public void throwException(Throwable throwable,AgentExecuteParam executeParam) {
        try {
            methodInterceptor.throwError(throwable,executeParam.getAgentTransferParam());
        } catch (Exception e) {
            agentLogger.error("异常抛出方法执行失败:"+e);
        }
    }


    /**
     * 拦截器
     * @param proxy
     * @param args
     * @param method
     * @param callable
     * @return
     */
    @RuntimeType
    public Object intercept(@This Object proxy,
                                   @AllArguments Object[] args,
                                   @Origin Method method,
                                   @SuperCall Callable<?> callable){
        AgentExecuteParam executeParam = new AgentExecuteParam(new AgentTransferParam());
        Object result = null;
        try {
            //传递调用caller的上下文扩展参数
            //之前执行方法
           before(proxy,args,method,executeParam);
            //调用父方法
           if(executeParam.isExecuteProtoMethod()) {
               result = callable.call();
           }
            //之后执行方法
           if(executeParam.isExecuteAfterMethod()) {
               after(proxy, args, method, result, executeParam);
           }
            return result;
        } catch (Throwable e) {
            throwException(e,executeParam);
            agentLogger.error("动态执行方法操作失败!"+e.getMessage());
        }
        return result;
    }
}
